package com.yshy.moviechoseseatinginnerapi.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.jhsjgo.commonmodel.base.ResultBean;
import cn.jhsjgo.commonmodel.config.request.RequestReqId;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yshy.moviechoseseatinginnerapi.service.OrdersService;
import com.yshy.moviechoseseatinginnerapi.service.TOrderCallbackService;
import com.yshy.moviechoseseatinginnerapi.service.TOrderService;
import com.yshy.moviechoseseatingcommon.entity.TOrder;
import com.yshy.moviechoseseatingcommon.entity.bo.orders.*;
import com.yshy.moviechoseseatingcommon.entity.dto.ComResponseDto;
import com.yshy.moviechoseseatingcommon.entity.dto.NoticeDto;
import com.yshy.moviechoseseatingcommon.entity.vo.orders.*;
import com.yshy.moviechoseseatingcommon.enums.OrderStateEnum;
import com.yshy.moviechoseseatingcommon.properties.CallbackProperties;
import com.yshy.moviechoseseatingcommon.properties.DockingInterfaceProperties;
import com.yshy.moviechoseseatingcommon.properties.NoticeProperties;
import com.yshy.moviechoseseatingcommon.util.RequstUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author :
 * @desc :
 * @create: 上午10:08
 **/
@Slf4j
@Service
public class OrdersServiceImpl implements OrdersService {
    @Autowired
    RequstUtil requstUtil;
    @Autowired
    TOrderService tOrderService;
    @Autowired
    DockingInterfaceProperties dockingInterfaceProperties;
    @Autowired
    CallbackProperties callbackProperties;
    @Autowired
    NoticeProperties noticeProperties;
    @Autowired
    TOrderCallbackService tOrderCallbackService;

    @Override
    public String getByOrderNo(GetByOrderNoBo bo) {
        GetByOrderNoVo getByOrderNoVo = requstUtil.ordersGetByOrderNo(bo);
        if(getByOrderNoVo==null){
            return "请求异常";
        }
        return JSONObject.toJSONString(getByOrderNoVo, SerializerFeature.WriteMapNullValue);
    }

    @Override
    public String getByPlatformOrderNo(GetByPlatformOrderNoBo bo) {
        if(bo.getPlatformOrderNo()==null){
            return "订单号不能为空";
        }
        GetByPlatformOrderNoVo getByPlatformOrderNoVo = requstUtil.ordersGetByPlatformOrderNo(bo);
//        //todo 模拟数据
//        GetByPlatformOrderNoVo getByPlatformOrderNoVo = new GetByPlatformOrderNoVo();
//        getByPlatformOrderNoVo.setSuccess(true);
//        getByPlatformOrderNoVo.setMessage("请求成功");
//        getByPlatformOrderNoVo.setCode(200);
//        GetByPlatformOrderNoVo.DataDTO dataDTO = new GetByPlatformOrderNoVo.DataDTO();
//        dataDTO.setCinemaName("熊出没");
//        dataDTO.setFilmName("范闲历险记");
//        dataDTO.setStatus(10);
//        GetByPlatformOrderNoVo.DataDTO.CouponsDTO couponsDTO = new GetByPlatformOrderNoVo.DataDTO.CouponsDTO();
//        couponsDTO.setCouponCode("1111111");
//        couponsDTO.setCouponCodeImageUrl("https://s.onfishes.com/static/mbsgetv2/Jiangxi_local_supermarket-down1.png");
//
//        GetByPlatformOrderNoVo.DataDTO.CouponsDTO couponsDTO2 = new GetByPlatformOrderNoVo.DataDTO.CouponsDTO();
//        couponsDTO2.setCouponCode("22222222222");
//        couponsDTO2.setCouponCodeImageUrl("https://s.onfishes.com/static/mbsget/choose-equtiy-twos.png");
//        List<GetByPlatformOrderNoVo.DataDTO.CouponsDTO> list= new ArrayList<>();
//        list.add(couponsDTO);
//        list.add(couponsDTO2);
//        dataDTO.setCoupons(list);
//        getByPlatformOrderNoVo.setData(dataDTO);
        if(getByPlatformOrderNoVo==null){
            return "请求异常";
        }
        return JSONObject.toJSONString(getByPlatformOrderNoVo,SerializerFeature.WriteMapNullValue);
    }

    @Override
    public String listByBatchOrderNos(ListByBatchOrderNosBo bo) {
        ListByBatchOrderNosVo listByBatchOrderNosVo = requstUtil.ordersListByBatchOrderNos(bo);
        if(listByBatchOrderNosVo==null){
            return "请求异常";
        }
        return JSONObject.toJSONString(listByBatchOrderNosVo,SerializerFeature.WriteMapNullValue);
    }

    @Override
    public String pagedQuery(PagedsQueryBo bo) {
        PagedsQueryVo pagedsQueryVo = requstUtil.ordersPagedQuery(bo);
        if(pagedsQueryVo==null){
            return "请求异常";
        }
        return JSONObject.toJSONString(pagedsQueryVo,SerializerFeature.WriteMapNullValue);
    }

    @Override
    public String createMovieOrder(OrderIdBo bo) {
        TOrder one = tOrderService.getOne(new LambdaQueryWrapper<TOrder>().eq(TOrder::getOrderId, bo.getOrderId()));
        CreateMovieOrderBo createMovieOrderBo = JSONObject.parseObject(one.getRequestParam(),CreateMovieOrderBo.class);
        createMovieOrderBo.setPlatformOrderNo(bo.getOrderId().toString());
        createMovieOrderBo.setNotifyUrl(callbackProperties.getUrl());
        CreateMovieOrderVo createMovieOrderVo = requstUtil.ordersCreateMovieOrder(createMovieOrderBo);
        if(createMovieOrderVo==null){
            return "请求异常";
        }
        if(!createMovieOrderVo.getSuccess()){
            one.setResponseParam(JSONObject.toJSONString(createMovieOrderVo));
            tOrderService.update(new LambdaUpdateWrapper<TOrder>().eq(TOrder::getOrderId, one.getOrderId())
                    .set(TOrder::getResponseParam, one.getResponseParam()));
            return JSONObject.toJSONString(createMovieOrderVo,SerializerFeature.WriteMapNullValue);
        }
        one.setOrderIdDown(createMovieOrderVo.getData().getOrderNo());
        one.setResponseParam(JSONObject.toJSONString(createMovieOrderVo));
        one.setCreateTime(LocalDateTime.now());
        one.setOrderState(createMovieOrderVo.getData().getStatus());
        tOrderService.update(new LambdaUpdateWrapper<TOrder>().eq(TOrder::getOrderId, one.getOrderId())
                .set(TOrder::getOrderIdDown, one.getOrderIdDown())
                .set(TOrder::getResponseParam, one.getResponseParam())
                .set(TOrder::getCreateTime, one.getCreateTime())
                .set(TOrder::getOrderState, one.getOrderState()));
        log.info("下单接口，请求id={}，请求参数={}，响应参数（订单）={}", RequestReqId.getReqId(), JSONObject.toJSONString(bo),JSONObject.toJSONString(createMovieOrderVo));
        return JSONObject.toJSONString(createMovieOrderVo,SerializerFeature.WriteMapNullValue);
    }

    @Override
    public String refundMovieOrder(RefundMovieOrderBo bo) {
        ComResponseDto comResponseDto = requstUtil.ordersRefundMovieOrder(bo);
        if(comResponseDto==null){
            return "请求异常";
        }
        if (comResponseDto.getSuccess()) {
            tOrderService.update(new LambdaUpdateWrapper<TOrder>().eq(TOrder::getOrderIdDown, bo.getOrderNo()).ne(TOrder::getOrderState, OrderStateEnum.CANCELED.getValue()).set(TOrder::getOrderState, OrderStateEnum.CANCELED.getValue()));
        }
        log.info("取消订单接口，请求id={}，请求地址={}，请求参数={}，响应参数={}", RequestReqId.getReqId(),dockingInterfaceProperties.getUrl().getOrdersRefundMovieOrder(), JSONObject.toJSONString(bo),JSONObject.toJSONString(comResponseDto));

        return JSONObject.toJSONString(comResponseDto,SerializerFeature.WriteMapNullValue);
    }

    @Override
    public ResultBean checkCreateOrder(CreateMovieOrderBo bo) {
        TOrder tOrder = new TOrder();
        tOrder.setOrderId(IdUtil.getSnowflakeNextId());
        tOrder.setRequestParam(JSONObject.toJSONString(bo));
        tOrder.setCheckTime(LocalDateTime.now());
        boolean save = tOrderService.save(tOrder);
        if(save){
            log.info("检查下单接口，请求id={}，请求参数={}，响应参数（订单）={}", RequestReqId.getReqId(), JSONObject.toJSONString(bo), tOrder.getOrderId().toString());
            return ResultBean.success(tOrder.getOrderId().toString());
        }else {
            return ResultBean.fail("保存失败");
        }
    }

    @Override
    public String notice(NoticeBo bo) throws NoSuchAlgorithmException {
        if(!bo.getPlatformId().equals(dockingInterfaceProperties.getPlatformId())){
            log.info( "上游通知,平台id不匹配，请求id={}，请求参数={}",RequestReqId.getReqId(),JSONObject.toJSONString(bo));
            return "平台id不匹配";
        }
        NoticeDto noticeDto = new NoticeDto();
        noticeDto.setOrderNo(bo.getOrderNo());
        noticeDto.setEventType(bo.getEventType());
        noticeDto.setPlatform(bo.getPlatform());
        noticeDto.setPlatformId(bo.getPlatformId());
        String params = JSONObject.toJSONString(noticeDto);
        String paramStr = sortJsonKeys(params) + dockingInterfaceProperties.getSecret();
        String sign = RequstUtil.md5(paramStr);
        if(!sign.equalsIgnoreCase(bo.getSign())){
            log.info( "上游通知,签名不匹配，请求id={}，请求参数={}",RequestReqId.getReqId(),JSONObject.toJSONString(bo));
            return "签名不匹配";
        }
        boolean update = tOrderService.update(new LambdaUpdateWrapper<TOrder>().eq(TOrder::getOrderIdDown, bo.getOrderNo())
                .ne(TOrder::getOrderState, OrderStateEnum.CANCELED.getValue()).ne(TOrder::getOrderState, OrderStateEnum.TRANSACTION_SUCCESS.getValue())
                        .set(TOrder::getOrderState, bo.getEventType()));
        NoticeCallbackBo noticeCallbackBo = new NoticeCallbackBo();
        noticeCallbackBo.setEventType(bo.getEventType());
        noticeCallbackBo.setTimestamp(new Date().getTime() / 1000);
        NoticeCallbackBo.DataDTO dataDTO = new NoticeCallbackBo.DataDTO();
        TOrder one = tOrderService.getOne(new LambdaQueryWrapper<TOrder>().eq(TOrder::getOrderIdDown, bo.getOrderNo()));
        if(update){
            log.info( "上游通知,订单表更新成功，请求id={}",RequestReqId.getReqId());

            noticeCallbackBo.setOrderNo(one.getOrderId().toString());
            noticeCallbackBo.setDownOderNo(one.getOrderIdDown());

            if(bo.getEventType().equals(OrderStateEnum.CANCELED.getValue())){
                dataDTO.setCancelReason(bo.getData().getCancelReason());
                noticeCallbackBo.setData(dataDTO);
                    String callback = requstUtil.notice(noticeCallbackBo);
                    if (callback.equals("success")) {
                        log.info("通知回调，请求id={}，请求地址={}，请求参数={}，响应参数={}", RequestReqId.getReqId(), noticeProperties.getUrl(), JSONObject.toJSONString(noticeCallbackBo), callback);
                    }else {
                        log.info( "通知回调，请求id={}，请求地址={}，请求参数={}，响应参数={}", RequestReqId.getReqId(),noticeProperties.getUrl(),JSONObject.toJSONString(noticeCallbackBo),callback);
                    }
                return "success";
            }else {
                dataDTO.setCancelReason(null);
                noticeCallbackBo.setData(dataDTO);
                    String callback = requstUtil.notice(noticeCallbackBo);
                    if (callback.equals("success")) {
                        log.info("通知回调，请求id={}，请求地址={}，请求参数={}，响应参数={}", RequestReqId.getReqId(), noticeProperties.getUrl(), JSONObject.toJSONString(noticeCallbackBo), callback);
                    }else {
                        log.info( "通知回调，请求id={}，请求地址={}，请求参数={}，响应参数={}", RequestReqId.getReqId(),noticeProperties.getUrl(),JSONObject.toJSONString(noticeCallbackBo),callback);
                    }
                return "success";
            }
        }else {
            return "fail";
        }
    }
    /**
     * 解析和排序 JSON 对象，并将排序后的键值对以 & 分隔
     *
     * @param params
     * @return
     */
    public static String sortJsonKeys(String params) {
        // 解析 JSON 字符串
        JSONObject jsonObject = JSON.parseObject(params);

        // 提取键值对并排序
        List<Map.Entry<String, Object>> entries = new ArrayList<>();
        Set<Map.Entry<String, Object>> entrySet = jsonObject.entrySet();
        for (Map.Entry<String, Object> entry : entrySet) {
            entries.add(entry);
        }

        // 排序
        Collections.sort(entries, new Comparator<Map.Entry<String, Object>>() {
            @Override
            public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });

        // 构建新的字符串
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < entries.size(); i++) {
            Map.Entry<String, Object> entry = entries.get(i);
            result.append(entry.getKey()).append("=").append(entry.getValue());
            if (i < entries.size() - 1) {
                result.append("&");
            }
        }

        return result.toString();
    }

//    /**
//     * 将字符串进行MD5加密
//     *
//     * @param content 要加密的内容
//     * @return 加密后的内容
//     * @throws NoSuchAlgorithmException
//     */
//    public static String md5(String content) throws NoSuchAlgorithmException {
//        MessageDigest md = MessageDigest.getInstance("MD5");
//        md.update(content.getBytes(Charset.forName("utf-8")));
//        byte[] digest = md.digest();
//        return DatatypeConverter.printHexBinary(digest);
//    }
}
